#pragma once

#include <boostext/util/make_shared.hpp>
#include <engine.core/vertices.hpp>

#include "Buffer.hpp"




namespace Engine
{
	namespace Video
	{
		/**
		 * A constant buffer groups together variables so that they can be set at once.
		 * It may be created from one input layout that may not change anymore during runtime.
		 * Just like a Mesh, it can be updated with a new value at any time.
		 */
		class ENGINE_VIDEO_API ConstantsBuffer : public Buffer
		{
		public:

			SHARED(ConstantsBuffer);



			/**
			 * Update the ConstantsBuffer with a new value.
			 * Use this function if you want to transfer one instance of
			 * the layout structure/class to the buffer.
			 */
			template <typename Structure>
			void update(const Structure& constants)
			{
				// Verify that this is no static buffer
				if(usage() == Buffer::Static)
					BOOSTEXT_THROW(programming_error("This ConstantsBuffer is static and therefore may not be changed anymore"));
				// Verify that the user doesn't give us another layout
				if(Structure::reflect() != reflect())
					BOOSTEXT_THROW(programming_error("A ConstantsBuffer is bound to the same Structure it has been created with"));

				update(&constants, sizeof(Structure));
			}

		protected:

			/**
			 * Update the ConstantsBuffer with new data.
			 *
			 * @param data         pointer to the actual data
			 * @param dataSize     size of the entire buffer (thus required size of the buffer)
			 */
			 virtual void update(const void* data, uint32 dataSize) = 0;

			 /**
			 * Get a pointer to the beginning of the buffer.
			 * The size of the requested data must be given in order to
			 * quickly spot errors.
			 */
			virtual void* data(uint32 dataSize) = 0;
		};
		///////////////////////////////////////////////////////////////////////////////////////////
	}
	///////////////////////////////////////////////////////////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////////////////////////////////////
